package com.dankegongyu.flutter_device_info;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.provider.MediaStore;
import android.provider.Settings;
import android.telephony.TelephonyManager;
import android.text.TextUtils;

import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import io.flutter.Log;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import io.flutter.plugin.common.MethodChannel.Result;
import io.flutter.plugin.common.PluginRegistry.Registrar;

/**
 * FlutterDeviceInfoPlugin
 */
public class FlutterDeviceInfoPlugin implements MethodCallHandler {
    private final Context context;

    /**
     * Do not allow direct instantiation.
     */
    private FlutterDeviceInfoPlugin(Context context) {
        this.context = context.getApplicationContext();
    }

    /**
     * Plugin registration.
     */
    public static void registerWith(Registrar registrar) {
        final MethodChannel channel = new MethodChannel(registrar.messenger(), "plugins/dk_flutter_device_info");
        channel.setMethodCallHandler(new FlutterDeviceInfoPlugin(registrar.context()));
    }

    @Override
    public void onMethodCall(final MethodCall call, final Result result) {
        if (call.method.equals("getHeaderInfo")) {
            Map<String, Object> build = new HashMap<>();
            build.put("os-type", "Android");
            build.put("os-ver", Build.VERSION.RELEASE);
            build.put("app-ver", "V" + getAppVersion(context.getApplicationContext()));
            build.put("net-type", getNetworkType());
            build.put("imei", Build.SERIAL + Settings.System.getString(context.getContentResolver(), Settings.System.ANDROID_ID));
            build.put("timestamp", String.valueOf((System.currentTimeMillis() / 1000)));
            build.put("device-uuid", UUID.randomUUID().toString().replaceAll("-", "") + "00000000");
            build.put("device-brand", Build.MANUFACTURER);
            String model = Build.MODEL;
            if (model != null) {
                model = model.trim().replaceAll("\\s*", "");
            } else {
                model = "";
            }
            build.put("device-model", model);
            build.put("app-channel", "danke");
            build.put("package-name", context.getPackageName());
            build.put("width", "" + context.getResources().getDisplayMetrics().widthPixels);
            build.put("height", "" + context.getResources().getDisplayMetrics().heightPixels);
            /*build.put("ClientId", "");
            build.put("loc_latlng", "");
            build.put("loc_city", "");
            build.put("loc_address", "");*/
            result.success(build);
        } else if (call.method.equals("getCacheInfo")) {
            Object spName = call.argument("spName");
            Object spKey = call.argument("spKey");
            if (null != spName && null != spKey) {
                result.success(getDebugInfo(spName.toString(), spKey.toString()));
            } else {
                result.success("");
            }
        } else if (call.method.equals("putCacheInfo")) {
            Object spName = call.argument("spName");
            Object spKey = call.argument("spKey");
            Object spValue = call.argument("spValue");
            if (null != spName && null != spKey && null != spValue) {
                result.success(putDebugInfo(spName.toString(), spKey.toString(), spValue.toString()));
            } else {
                result.success(false);
            }
        } else if (call.method.equals("refreshAlbum")) {
            Log.e("thread","============"+Thread.currentThread());
            Log.e("thread","============"+Thread.currentThread().getName());
            final Object imageAbsolutePath = call.argument("imageAbsolutePath");
            if (null == imageAbsolutePath) {
                result.success(false);
                return;
            }
            final Handler mainHandler = new Handler(Looper.getMainLooper());
            new Thread(new Runnable() {
                @Override
                public void run() {
                    Object isInsertGalleryObj = call.argument("isInsertAlbum");
                    boolean isInsertAlbum = false;
                    if (isInsertGalleryObj instanceof Boolean) {
                        isInsertAlbum = (boolean) isInsertGalleryObj;
                    }
                    try {
                        File file = new File(imageAbsolutePath.toString());
                        if (isInsertAlbum) {
                            Object isReplaceOldObj = call.argument("isReplaceOld");
                            boolean isReplaceOld = true;
                            if (isReplaceOldObj instanceof Boolean) {
                                isReplaceOld = (boolean) isReplaceOldObj;
                            }
                            if (!isReplaceOld) {
                                Cursor cursor = MediaStore.Images.Media.query(context.getContentResolver(), MediaStore.Images.Media.EXTERNAL_CONTENT_URI, new String[]{MediaStore.Images.Media.TITLE}, MediaStore.Images.Media.TITLE + "=?", new String[]{file.getName()}, null);
                                if (cursor.getCount() > 0) {//包含该图片
                                    result.success(true);
                                    return;
                                }
                            }
                            MediaStore.Images.Media.insertImage(context.getContentResolver(), file.getAbsolutePath(), file.getName(), file.getName());
                        }
                        /*// 最后通知图库更新
                        Intent scanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
                        Uri contentUri = Uri.parse("file://" + file.getAbsoluteFile());
                        scanIntent.setData(contentUri);
                        context.sendBroadcast(scanIntent);*/
                        Object isNotifyAlbumObj = call.argument("isNotifyAlbum");
                        boolean isNotifyAlbum = false;
                        if (isInsertGalleryObj instanceof Boolean) {
                            isNotifyAlbum = (boolean) isNotifyAlbumObj;
                        }
                        if (isNotifyAlbum) {
//                            MediaScannerConnection.scanFile(context, new String[]{file.getAbsolutePath()}, new String[]{"image/jpeg"}, new MediaScannerConnection.OnScanCompletedListener() {
//                                @Override
//                                public void onScanCompleted(String path, Uri uri) {
//                                    //result.success(true);
//                                }
//                            });
                            context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(file)));
                        }
                        mainHandler.post(new Runnable() {
                            @Override
                            public void run() {
                                result.success(true);
                                mainHandler.removeCallbacksAndMessages(null);
                            }
                        });
                    } catch (Exception exception) {
                        exception.printStackTrace();
                        mainHandler.post(new Runnable() {
                            @Override
                            public void run() {
                                result.success(false);
                                mainHandler.removeCallbacksAndMessages(null);
                            }
                        });
                    }
                }
            }).start();
        } else {
            result.notImplemented();
        }
    }

    /**
     * 获取版本号
     */
    private String getAppVersion(Context context) {
        String packageName = context.getApplicationContext().getPackageName();
        if (TextUtils.isEmpty(packageName)) return null;
        try {
            PackageManager pm = context.getApplicationContext().getPackageManager();
            PackageInfo pi = pm.getPackageInfo(packageName, 0);
            return pi == null ? null : pi.versionName;
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
            return null;
        }
    }

    private String getDebugInfo(String spName, String spKey) {
        if (null == context || null == spName || spName.trim().length() <= 0 || null == spKey || spKey.trim().length() <= 0) {
            return "";
        }
        SharedPreferences sp = context.getSharedPreferences(spName, Context.MODE_PRIVATE);
        if (null == sp) {
            return "";
        }
        return sp.getString(spKey, "");
    }

    private boolean putDebugInfo(String spName, String spKey, String spValue) {
        if (null == context || null == spName || spName.trim().length() <= 0 || null == spKey || spKey.trim().length() <= 0) {
            return false;
        }
        SharedPreferences sp = context.getSharedPreferences(spName, Context.MODE_PRIVATE);
        if (null == sp) {
            return false;
        }
        try {
            sp.edit().putString(spKey, spValue).commit();
            return true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * Returns the Android hardware device ID that is unique between the device + user and app
     * signing. This key will change if the app is uninstalled or its data is cleared. Device factory
     * reset will also result in a value change.
     *
     * @return The android ID
     */
    /*@SuppressLint("HardwareIds")
    private String getAndroidId() {
        return Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
    }*/

    /**
     * A simple emulator-detection based on the flutter tools detection logic and a couple of legacy
     * detection systems
     */
    private boolean isEmulator() {
        return (Build.BRAND.startsWith("generic") && Build.DEVICE.startsWith("generic"))
                || Build.FINGERPRINT.startsWith("generic")
                || Build.FINGERPRINT.startsWith("unknown")
                || Build.HARDWARE.contains("goldfish")
                || Build.HARDWARE.contains("ranchu")
                || Build.MODEL.contains("google_sdk")
                || Build.MODEL.contains("Emulator")
                || Build.MODEL.contains("Android SDK built for x86")
                || Build.MANUFACTURER.contains("Genymotion")
                || Build.PRODUCT.contains("sdk_google")
                || Build.PRODUCT.contains("google_sdk")
                || Build.PRODUCT.contains("sdk")
                || Build.PRODUCT.contains("sdk_x86")
                || Build.PRODUCT.contains("vbox86p")
                || Build.PRODUCT.contains("emulator")
                || Build.PRODUCT.contains("simulator");
    }


    /**
     * 获取活动网络信息
     * <p>需添加权限 {@code <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>}</p>
     *
     * @return NetworkInfo
     */
    @SuppressLint("MissingPermission")
    private NetworkInfo getActiveNetworkInfo() {
        return ((ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE)).getActiveNetworkInfo();
    }

    /**
     * 判断网络是否连接
     * <p>需添加权限 {@code <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>}</p>
     *
     * @return {@code true}: 是<br>{@code false}: 否
     */
    public boolean isConnected() {
        NetworkInfo info = getActiveNetworkInfo();
        return info != null && info.isConnected();
    }

    /**
     * 获取当前网络类型
     * <p>需添加权限 {@code <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>}</p>
     */
    public String getNetworkType() {
        String netType = "no";
        NetworkInfo info = getActiveNetworkInfo();
        if (info != null && info.isAvailable()) {

            if (info.getType() == ConnectivityManager.TYPE_WIFI) {
                netType = "wifi";
            } else if (info.getType() == ConnectivityManager.TYPE_MOBILE) {
                switch (info.getSubtype()) {

                    case TelephonyManager.NETWORK_TYPE_GSM:
                    case TelephonyManager.NETWORK_TYPE_GPRS:
                    case TelephonyManager.NETWORK_TYPE_CDMA:
                    case TelephonyManager.NETWORK_TYPE_EDGE:
                    case TelephonyManager.NETWORK_TYPE_1xRTT:
                    case TelephonyManager.NETWORK_TYPE_IDEN:
                        netType = "2g";
                        break;

                    case TelephonyManager.NETWORK_TYPE_TD_SCDMA:
                    case TelephonyManager.NETWORK_TYPE_EVDO_A:
                    case TelephonyManager.NETWORK_TYPE_UMTS:
                    case TelephonyManager.NETWORK_TYPE_EVDO_0:
                    case TelephonyManager.NETWORK_TYPE_HSDPA:
                    case TelephonyManager.NETWORK_TYPE_HSUPA:
                    case TelephonyManager.NETWORK_TYPE_HSPA:
                    case TelephonyManager.NETWORK_TYPE_EVDO_B:
                    case TelephonyManager.NETWORK_TYPE_EHRPD:
                    case TelephonyManager.NETWORK_TYPE_HSPAP:
                        netType = "3g";
                        break;

                    case TelephonyManager.NETWORK_TYPE_IWLAN:
                    case TelephonyManager.NETWORK_TYPE_LTE:
                        netType = "4g";
                        break;
                    default:

                        String subtypeName = info.getSubtypeName();
                        if (subtypeName.equalsIgnoreCase("TD-SCDMA")
                                || subtypeName.equalsIgnoreCase("WCDMA")
                                || subtypeName.equalsIgnoreCase("CDMA2000")) {
                            netType = "3g";
                        } else {
                            netType = "unknown";
                        }
                        break;
                }
            } else {
                netType = "unknown";
            }
        }
        return netType;
    }
}
